package com.pms.partitionPoints.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.SqlHelper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.pms.partitionPoints.bean.EquipmentBean;
import com.pms.partitionPoints.bean.EquipmentDataBean;
import com.pms.partitionPoints.entity.KyEquipmentInfo;
import com.pms.partitionPoints.entity.KyEquipmentUploadData;
import com.pms.partitionPoints.entity.KyOrganizationParameters;
import com.pms.partitionPoints.mapper.KyEquipmentInfoMapper;
import com.pms.partitionPoints.mapper.KyOrganizationMapper;
import com.pms.partitionPoints.mapper.KyOrganizationParametersMapper;
import com.pms.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.pms.partitionPoints.entity.KyOrganizationEquipment;
import com.pms.partitionPoints.mapper.KyOrganizationEquipmentMapper;
import com.pms.partitionPoints.service.IKyOrganizationEquipmentService;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

import static java.math.BigDecimal.ROUND_HALF_UP;

/**
 *
 * @author lk
 * @email 307169223@qq.com
 * @date 2018-07-24 11:38:28
 */
@Service
public class KyOrganizationEquipmentServiceImpl extends ServiceImpl<KyOrganizationEquipmentMapper,KyOrganizationEquipment> implements IKyOrganizationEquipmentService {

    @Autowired
    KyOrganizationParametersMapper kyOrganizationParametersMapper;
    @Autowired
    KyEquipmentInfoMapper kyEquipmentInfoMapper;
    @Autowired
    KyOrganizationMapper kyOrganizationMapper;

    public Page<EquipmentDataBean> queryEquipmentPages(Page<EquipmentDataBean> page, EntityWrapper ew,Integer orgMaxId){
        SqlHelper.fillWrapper(page, ew);
        page.setRecords(baseMapper.getEquipmentsByParam(page,ew,orgMaxId));
        return page;
    }

    public Page<KyEquipmentUploadData> queryEquipmentDateListById(Page<KyEquipmentUploadData> page, EntityWrapper ew,Integer orgId){
//        return baseMapper.getEquipmentDateListById(orgId,id);
        SqlHelper.fillWrapper(page,ew);
        page.setRecords(baseMapper.getEquipmentDateListById(page,ew,orgId));
        return page;
    }

    public List<KyEquipmentUploadData> getEquipmentDateByIdsAndTime(Integer orgId, Integer equipmentId, Date startTime, Date endTime){
        return baseMapper.selectEquipmentDateByIdAndTime(orgId,equipmentId,startTime,endTime);
    }

    public BigDecimal selectOrgWaterUsageByOrgIdAndTime(Integer orgMaxId,Integer orgId,Date startTime,Date endTime){
        List<Integer> equList = baseMapper.selectEquListByOrgId(orgId);
        BigDecimal countInstantaneousFlow = new BigDecimal(0.0),entryCountInstantaneousFlow= new BigDecimal(0.0);
        if(equList.size()>0){
            List<Map<String,Object>> list = baseMapper.selectOrgWaterUsageByOrgId(orgMaxId,equList,startTime,endTime,orgId);
            for(int i=0;i<list.size();i++){
                String direction = list.get(i).get("direction").toString();
                BigDecimal instantaneousFlow = (BigDecimal)list.get(i).get("flow");
                if("0".equals(direction)){
                    countInstantaneousFlow = countInstantaneousFlow.subtract(instantaneousFlow);
                }else{
                    countInstantaneousFlow = countInstantaneousFlow.add(instantaneousFlow);
                }
            }
        }
        return countInstantaneousFlow;
    }

    public BigDecimal getNewestFlowByOrgId(Integer orgMaxId,Integer orgId,Date startTime){
        List<Integer> equList = baseMapper.selectEquListByOrgId(orgId);
        BigDecimal countInstantaneousFlow = new BigDecimal(0.0),entryCountInstantaneousFlow= new BigDecimal(0.0);
        if(equList.size()>0){
            List<Map<String,Object>> list = baseMapper.selectNewestFlowByOrgIdAndequIdList(orgMaxId,equList,startTime);
            for(int i=0;i<list.size();i++){
                String direction = list.get(i).get("direction").toString();
                BigDecimal instantaneousFlow = (BigDecimal)list.get(i).get("instantaneousFlow");
                if("0".equals(direction)){
                    countInstantaneousFlow = countInstantaneousFlow.subtract(instantaneousFlow);
                }else{
                    countInstantaneousFlow = countInstantaneousFlow.add(instantaneousFlow);
                }
            }
        }
        return countInstantaneousFlow;
    }


    public List<Map<String,Object>> getOrgWaterDayByEquIdsAdTime(Integer orgMaxId,Integer orgId,Date startTime,Date endTime){
        //分区中所有的关联的计量测点
        List<KyOrganizationEquipment> list = baseMapper.selectList(new EntityWrapper<KyOrganizationEquipment>().eq("organizationId",orgId).
                and().in("direction","0,1"));

        List<KyOrganizationParameters> kopList =  kyOrganizationParametersMapper.selectList(new EntityWrapper<KyOrganizationParameters>().eq("organization_id",orgId));
        List<Integer> inList = new ArrayList<>();//所有进水口测点id集合
        List<Integer> outList = new ArrayList<>();//所有出水口测点id集合
        for(KyOrganizationEquipment koe:list){
            Integer direction = koe.getDirection();
            if(direction==0){
                outList.add(koe.getEquipmentid());
            }else{
                inList.add(koe.getEquipmentid());
            }
        }
        List<Map<String,Object>> outMapList = new ArrayList<>();//出水
        List<Map<String,Object>> inMapList = new ArrayList<>();//进水
        Map<String,Object> param = new HashMap<>();
        param.put("orgMaxId",orgMaxId);
        param.put("startTime",startTime);
        param.put("endTime",endTime);
        if(outList.size()>0){
            param.put("equIds",outList);
            outMapList = baseMapper.selectOrgWaterDayByEquIdsAndTime(param);
        }
        if(inList.size()>0){
            param.put("equIds",inList);
            inMapList = baseMapper.selectOrgWaterDayByEquIdsAndTime(param);
        }
        List<Map<String,Object>> flowList = new ArrayList<>();//返回数据
        BigDecimal outFlow = new BigDecimal(0.0);
        BigDecimal inFlow = new BigDecimal(0.0);
        BigDecimal flow = new BigDecimal(0.0);
        BigDecimal feeWaterConsumption = new BigDecimal(0.00).setScale(2, ROUND_HALF_UP);
        BigDecimal freeWaterConsumption = new BigDecimal(0.00).setScale(2, ROUND_HALF_UP);
        BigDecimal backgroundLeakage = new BigDecimal(0.00).setScale(2, ROUND_HALF_UP);
        BigDecimal noWaterConsumption = new BigDecimal(0.00).setScale(2, ROUND_HALF_UP);
        BigDecimal measureErrer = new BigDecimal(0.00).setScale(2, ROUND_HALF_UP);
        BigDecimal otherLossWater = new BigDecimal(0.00).setScale(2, ROUND_HALF_UP);
        BigDecimal ullage = new BigDecimal(0.00).setScale(2, ROUND_HALF_UP);//漏损量
        BigDecimal zero = new BigDecimal(0.00).setScale(2, ROUND_HALF_UP);//比较值为0
        if(outMapList.size()==0&&inMapList.size()>0){//进水口集合有值出水口无值
            for(Map<String,Object> map:inMapList){
                Date time = DateUtil.stringToDate((String)map.get("time"));
                int year = time.getYear()+1900;
                int month = time.getMonth()+1;
                int dayNum = DateUtil.getDaysByYearMonth(year,month);
                BigDecimal dayNumber = new BigDecimal(dayNum);
                KyOrganizationParameters kopParam = null;
                for(KyOrganizationParameters kop:kopList){
                    int year1 = kop.getYear();
                    int month1 = kop.getMonth();
                    if(year==year1&&month==month1){
                        kopParam = kop;
                    }
                }
                inFlow = (BigDecimal)map.get("flow");
                if(kopParam!=null){
                    feeWaterConsumption = (kopParam.getFeeWaterConsumption()).divide(dayNumber,2, ROUND_HALF_UP);//计费用水量
                    freeWaterConsumption = kopParam.getFreeWaterConsumption().divide(dayNumber,2, ROUND_HALF_UP);//免费用水量
                    backgroundLeakage = kopParam.getBackgroundLeakage().divide(dayNumber,2, ROUND_HALF_UP);//背景漏失
                    noWaterConsumption = kopParam.getNoWaterConsumption().divide(dayNumber,2, ROUND_HALF_UP);//未计量用水量
                    measureErrer = kopParam.getMeasureErrer().divide(dayNumber,2, ROUND_HALF_UP);//计量误差
                    otherLossWater = kopParam.getOtherLossWater().divide(dayNumber,2, ROUND_HALF_UP);//其他损失水量
                    flow = inFlow.subtract(feeWaterConsumption);
                }


                map.put("flow",flow);//产销差
                ullage = inFlow.subtract(freeWaterConsumption).subtract(backgroundLeakage).subtract(noWaterConsumption).subtract(measureErrer).subtract(otherLossWater);
                map.put("ullage",ullage);
                if(inFlow.compareTo(zero)==0){
                    map.put("leakage",0.00);
                }else{
                    map.put("leakage",ullage.divide(inFlow,2, ROUND_HALF_UP));
                }
                map.put("time",time);
                flowList.add(map);
            }
        }else if(outMapList.size()>0&&inMapList.size()==0){//出水口集合有值而进水口无值
            for(Map<String,Object> map:outMapList){
                Date time = DateUtil.stringToDate((String)map.get("time"));
                int year = time.getYear()+1900;
                int month = time.getMonth()+1;
                int dayNum = DateUtil.getDaysByYearMonth(year,month);
                BigDecimal dayNumber = new BigDecimal(dayNum);
                KyOrganizationParameters kopParam = null;
                for(KyOrganizationParameters kop:kopList){
                    int year1 = kop.getYear();
                    int month1 = kop.getMonth();
                    if(year==year1&&month==month1){
                        kopParam = kop;
                    }
                }
                outFlow = (BigDecimal)map.get("flow");
                if(kopParam!=null){
                    feeWaterConsumption = kopParam.getFeeWaterConsumption().divide(dayNumber,2, ROUND_HALF_UP);//计费用水量
                    freeWaterConsumption = kopParam.getFreeWaterConsumption().divide(dayNumber,2, ROUND_HALF_UP);//免费用水量
                    backgroundLeakage = kopParam.getBackgroundLeakage().divide(dayNumber,2, ROUND_HALF_UP);//背景漏失
                    noWaterConsumption = kopParam.getNoWaterConsumption().divide(dayNumber,2, ROUND_HALF_UP);//未计量用水量
                    measureErrer = kopParam.getMeasureErrer().divide(dayNumber,2, ROUND_HALF_UP);//计量误差
                    otherLossWater = kopParam.getOtherLossWater().divide(dayNumber,2, ROUND_HALF_UP);//其他损失水量
                }
                flow = outFlow.add(feeWaterConsumption).negate();
                ullage = flow.subtract(freeWaterConsumption).subtract(backgroundLeakage).subtract(noWaterConsumption).subtract(measureErrer).subtract(otherLossWater);
                map.put("flow",flow);
                map.put("ullage",ullage);
                if(flow.compareTo(zero)==0){
                    map.put("leakage",0.00);
                }else{
                    map.put("leakage",ullage.divide(outFlow.negate(),2, ROUND_HALF_UP));
                }
                map.put("time",time);
                flowList.add(map);
            }
        } else if(outMapList.size()>0&&inMapList.size()>0){//进出水口都有值
            for(Map<String,Object> map:inMapList){
                Date inTime = DateUtil.stringToDate((String)map.get("time"));
                inFlow = (BigDecimal)map.get("flow");
                int year = inTime.getYear()+1900;
                int month = inTime.getMonth()+1;
                int dayNum = DateUtil.getDaysByYearMonth(year,month);
                BigDecimal dayNumber = new BigDecimal(dayNum);
                KyOrganizationParameters kopParam = null;
                for(KyOrganizationParameters kop:kopList){
                    int year1 = kop.getYear();
                    int month1 = kop.getMonth();
                    if(year==year1&&month==month1){
                        kopParam = kop;
                    }
                }
                if(kopParam!=null){
                    feeWaterConsumption = kopParam.getFeeWaterConsumption().divide(dayNumber,2, ROUND_HALF_UP);//计费用水量
                    freeWaterConsumption = kopParam.getFreeWaterConsumption().divide(dayNumber,2, ROUND_HALF_UP);//免费用水量
                    backgroundLeakage = kopParam.getBackgroundLeakage().divide(dayNumber,2, ROUND_HALF_UP);//背景漏失
                    noWaterConsumption = kopParam.getNoWaterConsumption().divide(dayNumber,2, ROUND_HALF_UP);//未计量用水量
                    measureErrer = kopParam.getMeasureErrer().divide(dayNumber,2, ROUND_HALF_UP);//计量误差
                    otherLossWater = kopParam.getOtherLossWater().divide(dayNumber,2, ROUND_HALF_UP);//其他损失水量
                }
                for(int i=0;i<outMapList.size();i++){
                    Map<String,Object> flowMap = new HashMap<>();
                    Date outTime = DateUtil.stringToDate((String)outMapList.get(i).get("time"));
                    outFlow = (BigDecimal)outMapList.get(i).get("flow");
                    if(outTime.equals(inTime)){
                        flow = inFlow.subtract(outFlow).subtract(feeWaterConsumption);
                        ullage = flow.subtract(freeWaterConsumption).subtract(backgroundLeakage).subtract(noWaterConsumption).subtract(measureErrer).subtract(otherLossWater);
                        flowMap.put("time",outTime);
                        flowMap.put("flow",flow);
                        flowMap.put("ullage",ullage);
                        if(flow.compareTo(zero)==0){
                            flowMap.put("leakage",0.00);
                        }else{
                            flowMap.put("leakage",ullage.divide(inFlow.subtract(outFlow),2, ROUND_HALF_UP));
                        }
                        flowList.add(flowMap);
                        break;
                    }else{//如果这天没有上报出水数据
                        if(i==outMapList.size()-1){//循环的最后一条数据(入水口当天无值而出水口有值)
                            flowMap.put("time",outTime);
                            flow = outFlow.negate().subtract(feeWaterConsumption);
                            flowMap.put("flow",flow);
                            ullage = flow.subtract(freeWaterConsumption).subtract(backgroundLeakage).subtract(noWaterConsumption).subtract(measureErrer).subtract(otherLossWater);
                            flowMap.put("ullage",ullage);
                            if(flow.compareTo(zero)==0){
                                flowMap.put("leakage",0.00);
                            }else{
                                flowMap.put("leakage",ullage.divide(outFlow.negate(),2, ROUND_HALF_UP));
                            }
                            flowList.add(flowMap);
                        }
                    }

                }
            }
        }
        return flowList;
    }

    public Page<EquipmentDataBean> queryEquipmentPages(Page<EquipmentDataBean> page, EntityWrapper ew,Integer orgMaxId,List<Integer> list,Date startTime,Date endTime,String name){
        SqlHelper.fillWrapper(page, ew);
        page.setRecords(baseMapper.getEquipmentsByParamNew(page,ew,orgMaxId,list,startTime,endTime,name));
        return page;
    }

    public List<Map<String,Object>> getEquipmentByOrgMaxId(int orgMaxId){
        return baseMapper.getEquipmentByOrgMaxId(orgMaxId);
    }

    public  List<Integer> getEquipmentsByOrganizationList(String organizationIdList){
        return baseMapper.getEquipmentsByOrganizationList(organizationIdList);
    }

    public Set<Map<String,Object>> getEquipmentDateByIdListAndTime(Integer orgId, List<Integer> equList, Date startTime, Date endTime,String param){
        Set<Map<String,Object>> set = new HashSet<>();
        for(Integer id:equList){
            Map<String,Object> map = new HashMap<>();
            List<Map<String,Object>> list = baseMapper.selectEquipmentDateListByIdAndTime(orgId,id,startTime,endTime,param);
            if(list.size()==0||list==null){
                continue;
            }
            KyEquipmentInfo ko = kyEquipmentInfoMapper.selectById(id);
            map.put("name",ko.getName());
            map.put("id",id);
            map.put("list",list);
            set.add(map);
        }
        return set;
    }

    public  List<EquipmentBean> getEquipmentDateByIdAndTime( Integer orgId, List<String> list, Date startTime, Date endTime){
        return baseMapper.getEquipmentDateByIdAndTime(orgId,list,startTime,endTime);
    }

    @Override
    public int getEquipmentNumByOrgMaxIdAndStatus(int orgMaxId, int equipmentStatus) {
        String orgIds = kyOrganizationMapper.findOrgIdsBycCurrentId(orgMaxId);
        List<String> strList = new ArrayList<String>();
        if(orgIds!=""&&orgIds!=null){
            String[] idStr = orgIds.split(",");
            strList = Arrays.asList(idStr);
        }
        return baseMapper.getEquipmentNumByOrgMaxIdAndStatus(strList,equipmentStatus);
    }
}